// 代码题一 将下面异步代码用Promise改进。
// setTimeout(function(){
//     var a = 'hello';
//     setTimeout(function(){
//         var b = 'lagou';
//         setTimeout(function(){
//             var c = 'i love u';
//             console.log(a+b+c);
//         },10)
//     },10)
// },10)

// const promise  = value => new Promise(resolve=>{
//     setTimeout(()=>{
//         resolve(value)
//     },10)
// });

// async function main () {
//     const a = await promise('hello');
//     const b = await promise('lagou');
//     const c = await promise('i love u');
//     console.log(a+b+c);
// }

// main();



// 代码题二 基于以下代码完成下面的四个练习
const { flow } = require('lodash');
const fp = require('lodash/fp');
// 数据
// horsepower 马力， dollar_value 价格, in_stock 库存
const cars = [
  {
    name: 'Ferrari FF',
    horsepower: 660,
    dollar_value: 700000,
    in_stock: true
  },
  {
    name: 'Spyker C12 Zagato',
    horsepower: 650,
    dollar_value: 64800,
    in_stock: false
  },
  {
    name: 'Jaguar XKR-S',
    horsepower: 550,
    dollar_value: 132000,
    in_stock: false
  },
  {
    name: 'Audi R8',
    horsepower: 525,
    dollar_value: 114200,
    in_stock: false
  },
  {
    name: 'Aston Martin One-77',
    horsepower: 750,
    dollar_value: 185000,
    in_stock: true
  },
  {
    name: 'Pagani Huayra',
    horsepower: 700,
    dollar_value: 130000,
    in_stock: false
  },
];
//  练习1： 使用函数组合fp.flowRight()重新实现下面这个函数
// let isLastInStock = function(cars){
//   // 获取最后一条数据
//   let last_car = fp.last(cars);
//   // 获取最后一条数据的in_stock属性值
//   return fp.prop('in_stock',last_car)
// }
// console.log(isLastInStock(cars));
// const isLastInStock =  fp.flowRight(fp.prop('in_stock'),fp.last);
// console.log(isLastInStock(cars));

//  练习2： 使用fp.flowRight()、fp.prop()和fp.first()获取第一个car的name
// const getFirstName = fp.flowRight(fp.prop('name'),fp.first);
// console.log(getFirstName(cars));

//  练习3： 使用帮助函数_average重构averageDollarValue,使用函数组合的方式实现
// let _average = function(xs) {
//   return fp.reduce(fp.add,0,xs)/xs.length
// }
// let averageDollarValue = function (cars){
//   let dollar_value = fp.map(function(cars){
//     return cars.dollar_value;
//   },cars);
//   return _average(dollar_value)
// }
// const averageDollarValue = fp.flowRight(_average,fp.map(fp.prop('dollar_value')));
// console.log(averageDollarValue(cars));

// 练习4： 使用flowRight写一个sanitizeNames()函数，返回一个下划线连接的小写字符串，把数组中的name转换为这种形式：例如：
// sanitizeNames(['Hello World'])=>['hello_world'];
// const _underscore = fp.replace(/\W+/g,'_');
// const sanitizeNames = fp.flowRight(_underscore,fp.map(fp.lowerCase));
// console.log(sanitizeNames(['Hello World']));



// 代码题三、基于下面提供的代码，完成后续的四个练习
// support.js
class Container {
  static of(value) {
    return new Container(value);
  }
  constructor(value) {
    this._value = value;
  }
  map(fn) {
    return Container.of(fn(this._value));
  }
}
class Maybe {
  static of(x) {
    return new Maybe(x)
  }
  isNothing() {
    return this._value === null || this._value === undefined;
  }
  constructor(x) {
    this._value = x
  }
  map(fn) {
    return this.isNothing() ? this : Maybe.of(fn(this._value));
  }
}

// 练习1： 使用fp.add(x,y)和fp.map(f,x)创建一个能让functor里的值增加的函数ex1
// let maybe = Maybe.of([5, 6, 1]);
// let ex1 = arr => {
//   return fp.map(fp.add(1),arr);
// }
// let a = maybe.map(ex1);
// console.log(a);

// 练习2： 实现一个函数ex2,能够使用fp.first获取列表的第一个元素
// let xs = Container.of([ 'do', 'ray', 'me', 'fa', 'so', 'la', 'ti', 'do' ]);
// let ex2 = arr => {
//   return fp.first(arr);
// }
// let a = xs.map(ex2);
// console.log(a);

// 练习3： 实现一个函数ex3,使用safeProp和fp.first找到user的名字的首字母
// let safeProp = fp.curry(function(x,o){
//   return Maybe.of(o[x])
// });
// let user = { id : 2, name : 'Albert' };
// let ex3 = x => {
//   return fp.first(x)
// }
// let a = safeProp('name',user).map(ex3);
// console.log(a);

// 练习4: 使用Maybe重写ex4, 不要有if语句
// let ex4 = function(n) {
//   if(n) {
//     return parseInt(n)
//   }
// }
// let ex4 = n => Maybe.of(parseInt(n));
// console.log(ex4(null));

// 代码题4： 手写promise源码，尽可能还原
// const PENDING = 'pending'; // 等待
// const FULFILLED = 'fulfilled'; // 成功
// const REJECTED = 'rejected'; // 等待

// class MyPromise {
//   constructor(executor) { // 执行器
//     executor(this.resolve, this.reject)
//   }
//   // 箭头函数（调用时，resolve 直接调用的，箭头函数使this指向promise类而不是window）
//   ststus = PENDING;        // 状态常量
//   value = undefined;       // 成功的值
//   reason = undefined;      // 失败的原因
//   successCallback = [];   // 成功回调
//   failCallback = []; // 失败回调
//   resolve = value => {
//     // 如果状态不是等待 阻止程序向下执行
//     if (this.ststus !== PENDING) return;
//     // 更改状态为成功
//     this.ststus = FULFILLED;
//     // 保存成功之后的值
//     this.value = value;
//     // 判断成功回调是否存在 存在就调用
//     // this.successCallback && this.successCallback(this.value);
//     while(this.successCallback.length){ this.successCallback.shift()(this.value) }
//   }
//   reject = reason => {
//     // 如果状态不是等待 阻止程序向下执行
//     if (this.ststus !== PENDING) return;
//     // 更改状态为失败
//     this.ststus = REJECTED;
//     // 保存失败后的原因
//     this.reason = reason;
//     // 判断失败回调是否存在 存在就调用
//     // this.failCallback && this.failCallback(this.reason);
//     while(this.failCallback.length){ this.failCallback.shift()(this.value) }
//   }
//   then(successCallback, failCallback) {
//     // 判断状态
//     if (this.ststus === FULFILLED) {
//       successCallback(this.value);
//     }else if (this.ststus === REJECTED) {
//       failCallback(this.reason);
//     } else {
//       // 等待
//       // 将成功回调、失败回调存储起来
//       this.successCallback.push(successCallback);
//       this.failCallback.push(failCallback);
//     }
//   }
// }